﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using NETMovie.BLL;
using NETMovie.Entities;
using NETMovie.UI.WebMVC.Mappers;
using NETMovie.UI.WebMVC.Models;
using System.Configuration;

namespace NETMovie.UI.WebMVC.Controllers
{
    public class RentalController : Controller
    {
        private IEnumerable<SelectListItem> GetCountries()
        {
            AccountService service = new AccountService();
            NETMovie.Entities.Country[] countries = service.GetCountries();
            if (countries == null || countries.Length == 0)
                return new List<SelectListItem>();

            SelectListItem[] items = new SelectListItem[countries.Length];

            for (int i = 0; i < countries.Length; i++)
            {
                items[i] = new SelectListItem();
                items[i].Value = countries[i].CountryCode;
                items[i].Text = countries[i].CountryName;
            }

            return items;
        }

        private IEnumerable<SelectListItem> GetCreditCards()
        {
            TransactionService service = new TransactionService();
            List< KeyValuePair<int, string> > cards = service.GetCreditCards();

            if (cards == null || cards.Count == 0)
                return new List<SelectListItem>();

            SelectListItem[] items = new SelectListItem[cards.Count];

            for (int i = 0; i < cards.Count; i++)
            {
                items[i] = new SelectListItem();
                items[i].Value = cards[i].Key.ToString();
                items[i].Text = cards[i].Value;
            }

            return items;
        }

        private void HandleErrors()
        {
            List<string> errors = TempData["Errors"] as List<string>;
            if (errors == null)
                return;

            AddErrors(errors);
        }

        private void AddErrors(List<string> errors)
        {
            foreach (string error in errors)
            {
                ModelState.AddModelError(error, error);
            }
        }

        [Authorize]
        public ActionResult RentMovie(int id)
        {
            int movieID = id;

            TransactionService service = new TransactionService();
            Transaction trans = null;

            trans = service.RentMovie(User.Identity.Name, movieID);

            if (trans == null)
            {
                TempData["Errors"] = service.Errors;
                
            }

            return RedirectToAction("ViewMovieDetails", "MovieStream", new { id = movieID });
        }

        [Authorize]
        [HttpGet]
        public ActionResult ViewRentalCart()
        {
            HandleErrors();

            TransactionService service = new TransactionService();
            Transaction trans = null;
            trans = service.GetOpenTransaction(User.Identity.Name);
            if (trans == null)
            {
                TempData["Errors"] = service.Errors;
                return RedirectToAction("Home", "Index");
            }

            TransactionMapper mapper = new TransactionMapper();
            ViewRentalCartModel model = mapper.ReMap(trans);
            ViewData["Mode"] = "D";

            return View(model);
        }

        [Authorize]
        [HttpPost]
        public ActionResult ViewRentalCart(ViewRentalCartModel rentalModel)
        {
            HandleErrors();

            if (!ModelState.IsValid)
                return View(rentalModel);

            TempData["RentalModel"] = rentalModel;
            return RedirectToAction("MakePayment");
        }

        [Authorize]
        [HttpGet]
        public ActionResult MakePayment()
        {
            HandleErrors();

            ViewRentalCartModel rentalModel = TempData["RentalModel"] as ViewRentalCartModel;
            User user = null;

            {
                AccountService service = new AccountService();
                user = service.GetUser(User.Identity.Name);
            }

            PaymentMapper mapper = new PaymentMapper();
            PaymentModel model = mapper.ReMap(rentalModel, user);
            model.Countries = GetCountries();
            model.CCTypes = GetCreditCards();
            model.CCType = "0";

            return View(model);
        }

        [Authorize]
        [HttpPost]
        public ActionResult MakePayment(PaymentModel model)
        {
            HandleErrors();

            if (!ModelState.IsValid)
            {
                model.Countries = GetCountries();
                model.CCTypes = GetCreditCards();
            
                return View(model);
            }

            PaymentMapper mapper = new PaymentMapper();
            Payment payment = mapper.Map(model);

            TransactionService service = new TransactionService();
            bool result = service.Checkout(payment);

            if (!result)
            {
                AddErrors(service.Errors);
                model.Countries = GetCountries();
                model.CCTypes = GetCreditCards();

                return View(model);
            }

            TempData["PaymentModel"] = model;
            TempData["GWTransactionID"] = payment.GWTransactionID;

            return RedirectToAction("ShowPaymentSummary");
        }

        [Authorize]
        [HttpGet]
        public ActionResult ShowPaymentSummary()
        {
            PaymentModel model = TempData["PaymentModel"] as PaymentModel;
            string gwTransID = TempData["GWTransactionID"] as string;

            // Prepare the model for the Payment Summary screen
            PaymentSummaryModel summaryModel = new PaymentSummaryModel();

            TransactionService service = new TransactionService();
            Transaction trans = service.GetTransaction(model.TransactionID);
            
            TransactionMapper transMapper = new TransactionMapper();
            ViewRentalCartModel cartModel = transMapper.ReMap(trans);
            ViewData["Mode"] = "W";

            summaryModel.CartInfo = cartModel;
            summaryModel.GWTransactionNo = gwTransID;

            return View(summaryModel);
        }

        [Authorize]
        [HttpGet]
        public ActionResult ViewMyRentals()
        {
            string username = User.Identity.Name;
            TransactionService service = new TransactionService();
            MovieRental[] rentals = service.GetActiveRentals(User.Identity.Name);

            RentalMapper mapper = new RentalMapper();
            ViewRentalsModel model = mapper.ReMap(rentals);

            ViewData["Mode"] = "RW";

            return View(model);
        }

        [Authorize]
        [HttpGet]
        public ActionResult DeleteRental(int id)
        {
            int rentalID = id;

            TransactionService service = new TransactionService();
            bool result = service.UnrentMovie(rentalID);
            if (!result)
            {
                TempData["Errors"] = service.Errors;
            }

            return RedirectToAction("ViewRentalCart");
        }

        [Authorize]
        [HttpGet]
        public ActionResult WatchMovie(int id)
        {
            int rentalID = id;
            WatchMovieModel model = null;
            TransactionService service = new TransactionService();
            Movie movie = service.GetMovieByRental(User.Identity.Name, rentalID);

            if (movie == null)
            {
                AddErrors(service.Errors);
            }
            else
            {
                MovieMapper mapper = new MovieMapper();
                model = mapper.ReMap(movie);
                if (!String.IsNullOrEmpty(model.MoviePath))
                {
                    string url = "http://" + Request.Url.Host + ":" + Request.Url.Port + ConfigurationManager.AppSettings["UploadsPath"] + model.MoviePath;
                    model.MoviePath = url;
                }
            }

            return View(model);
        }

        public ActionResult ReturnMovie(int id)
        {
            int rentalID = id;

            TransactionService service = new TransactionService();
            bool result = service.ReturnMovie(rentalID);
            if (!result)
            {
                TempData["Errors"] = service.Errors;
            }

            return RedirectToAction("ViewMyRentals");
        }
    }
}
